// 玩家领域服务

import { Player, Achievement, PlayerStats, SkillLevel } from '../models/Player';

/**
 * 玩家服务接口
 */
export interface IPlayerService {
  /**
   * 创建新玩家
   * @param name 玩家名称
   * @param avatar 头像URL
   * @returns 新创建的玩家对象
   */
  createPlayer(name: string, avatar?: string): Promise<Player>;

  /**
   * 根据ID获取玩家
   * @param playerId 玩家ID
   * @returns 玩家对象，如果不存在则返回null
   */
  getPlayerById(playerId: number): Promise<Player | null>;

  /**
   * 获取所有玩家
   * @returns 玩家列表
   */
  getAllPlayers(): Promise<Player[]>;

  /**
   * 更新玩家信息
   * @param playerId 玩家ID
   * @param updates 要更新的字段
   * @returns 更新后的玩家对象
   */
  updatePlayer(playerId: number, updates: Partial<Player>): Promise<Player | null>;

  /**
   * 删除玩家
   * @param playerId 玩家ID
   * @returns 是否删除成功
   */
  deletePlayer(playerId: number): Promise<boolean>;

  /**
   * 为玩家添加经验值
   * @param playerId 玩家ID
   * @param exp 要添加的经验值
   * @returns 是否升级
   */
  addExperience(playerId: number, exp: number): Promise<boolean>;

  /**
   * 为玩家解锁成就
   * @param playerId 玩家ID
   * @param achievement 成就信息
   * @returns 是否解锁成功
   */
  unlockAchievement(playerId: number, achievement: Omit<Achievement, 'unlockedAt'>): Promise<boolean>;

  /**
   * 更新玩家案件统计
   * @param playerId 玩家ID
   * @param caseResult 案件结果
   * @param playTime 游戏时间（分钟）
   */
  updateCaseStats(playerId: number, caseResult: 'success' | 'failure', playTime: number): Promise<void>;

  /**
   * 获取玩家排行榜
   * @param limit 限制返回数量
   * @returns 玩家排行榜列表
   */
  getPlayerRanking(limit: number = 10): Promise<Array<{ id: number; name: string; level: number; casesSolved: number }>>;
}

/**
 * 玩家服务实现类
 */
export class PlayerService implements IPlayerService {
  // 这里应该注入数据访问层的依赖
  // 由于是演示，我们使用内存存储
  private players: Player[] = [];
  private nextPlayerId: number = 1;

  /**
   * 创建新玩家
   */
  async createPlayer(name: string, avatar?: string): Promise<Player> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));

    const newPlayer = new Player(this.nextPlayerId++, name, avatar);
    this.players.push(newPlayer);
    
    // 解锁「新手上路」成就
    this.unlockAchievement(newPlayer.id, {
      id: 1,
      name: '新手上路',
      description: '创建你的第一个侦探角色',
      points: 50,
      icon: 'beginner'
    });
    
    return newPlayer;
  }

  /**
   * 根据ID获取玩家
   */
  async getPlayerById(playerId: number): Promise<Player | null> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 50));
    return this.players.find(p => p.id === playerId) || null;
  }

  /**
   * 获取所有玩家
   */
  async getAllPlayers(): Promise<Player[]> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));
    return [...this.players];
  }

  /**
   * 更新玩家信息
   */
  async updatePlayer(playerId: number, updates: Partial<Player>): Promise<Player | null> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));
    
    const playerIndex = this.players.findIndex(p => p.id === playerId);
    if (playerIndex === -1) return null;
    
    // 更新玩家信息（注意不直接替换整个对象，而是合并更新）
    const player = this.players[playerIndex];
    
    // 更新基本信息
    if (updates.name) player.name = updates.name;
    if (updates.avatar) player.avatar = updates.avatar;
    
    // 注意：等级、经验值等应由系统内部逻辑更新，不允许直接修改
    
    // 更新最后登录时间
    player.lastLoginDate = new Date().toISOString();
    
    this.players[playerIndex] = player;
    return player;
  }

  /**
   * 删除玩家
   */
  async deletePlayer(playerId: number): Promise<boolean> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 100));
    
    const initialLength = this.players.length;
    this.players = this.players.filter(p => p.id !== playerId);
    return this.players.length < initialLength;
  }

  /**
   * 为玩家添加经验值
   */
  async addExperience(playerId: number, exp: number): Promise<boolean> {
    const player = await this.getPlayerById(playerId);
    if (!player) return false;
    
    // 添加经验值并检查是否升级
    const didLevelUp = player.addExperience(exp);
    
    // 如果升级，可能需要解锁相关成就
    if (didLevelUp) {
      this.checkLevelAchievements(player);
    }
    
    return didLevelUp;
  }

  /**
   * 为玩家解锁成就
   */
  async unlockAchievement(playerId: number, achievement: Omit<Achievement, 'unlockedAt'>): Promise<boolean> {
    const player = await this.getPlayerById(playerId);
    if (!player) return false;
    
    return player.unlockAchievement(achievement);
  }

  /**
   * 更新玩家案件统计
   */
  async updateCaseStats(playerId: number, caseResult: 'success' | 'failure', playTime: number): Promise<void> {
    const player = await this.getPlayerById(playerId);
    if (!player) return;
    
    // 更新统计信息
    player.updateCaseStats(caseResult, playTime);
    
    // 完成案件后检查是否可以解锁相关成就
    if (caseResult === 'success') {
      this.checkCaseAchievements(player);
      // 成功破案增加相关技能经验
      player.addSkillExperience('deduction', 20);
      player.addSkillExperience('analysis', 15);
    }
    
    // 增加观察技能经验（无论成功失败都有收获）
    player.addSkillExperience('observation', 10);
  }

  /**
   * 获取玩家排行榜
   */
  async getPlayerRanking(limit: number = 10): Promise<Array<{ id: number; name: string; level: number; casesSolved: number }>> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 150));
    
    return this.players
      .sort((a, b) => {
        // 首先按等级排序，然后按解决的案件数排序
        if (b.level !== a.level) {
          return b.level - a.level;
        }
        return b.stats.casesSolved - a.stats.casesSolved;
      })
      .slice(0, limit)
      .map(p => ({
        id: p.id,
        name: p.name,
        level: p.level,
        casesSolved: p.stats.casesSolved
      }));
  }

  /**
   * 检查等级相关成就
   */
  private checkLevelAchievements(player: Player): void {
    const levelAchievements: Array<{ level: number; achievement: Omit<Achievement, 'unlockedAt'> }> = [
      {
        level: 5,
        achievement: {
          id: 5,
          name: '初露锋芒',
          description: '达到5级，成为一名中级侦探',
          points: 200,
          icon: 'level5'
        }
      },
      {
        level: 10,
        achievement: {
          id: 10,
          name: '名侦探',
          description: '达到10级，成为一名高级侦探',
          points: 500,
          icon: 'level10'
        }
      },
      {
        level: 20,
        achievement: {
          id: 20,
          name: '传奇诞生',
          description: '达到20级，成为传奇侦探',
          points: 1000,
          icon: 'legend'
        }
      }
    ];

    // 检查并解锁等级成就
    for (const { level, achievement } of levelAchievements) {
      if (player.level === level) {
        player.unlockAchievement(achievement);
      }
    }
  }

  /**
   * 检查案件相关成就
   */
  private checkCaseAchievements(player: Player): void {
    const caseAchievements: Array<{ casesSolved: number; achievement: Omit<Achievement, 'unlockedAt'> }> = [
      {
        casesSolved: 1,
        achievement: {
          id: 2,
          name: '初次破案',
          description: '成功解决第一个案件',
          points: 100,
          icon: 'first_case'
        }
      },
      {
        casesSolved: 10,
        achievement: {
          id: 6,
          name: '侦探达人',
          description: '成功解决10个案件',
          points: 300,
          icon: 'detective_master'
        }
      },
      {
        casesSolved: 50,
        achievement: {
          id: 11,
          name: '犯罪克星',
          description: '成功解决50个案件',
          points: 800,
          icon: 'crime_fighter'
        }
      }
    ];

    // 检查并解锁案件成就
    for (const { casesSolved, achievement } of caseAchievements) {
      if (player.stats.casesSolved === casesSolved) {
        player.unlockAchievement(achievement);
      }
    }

    // 检查准确率成就
    if (player.stats.casesSolved >= 5 && player.stats.accuracyRate >= 90) {
      player.unlockAchievement({
        id: 3,
        name: '明察秋毫',
        description: '保持90%以上的破案准确率',
        points: 250,
        icon: 'accuracy'
      });
    }
  }
}